/**
 * 导航视图
 */
function scElementView(){
    var com = scCommon.instance();
    var crEle = com.crEle;

    var box = null;
    var preview = null;

    var tab = null;
    var lastTabItem = null;

    var list = [
        {label: "文档结构", name: "documentStruct", class: "step-1", command: "getPageList", active: true},
        {label: "元素结构", name: "elementStruct", class: "step-2", command: ""},
        {label: "元素属性", name: "elementProperties", class: "step-3", command: ""}
    ]

    var listener = null;
    var wrapHeight = 0;

    /**
     * 创建视图
     * @param {*} option
     * @returns 
     */
    this.createView = function(option){
        option = option ? option : {};
        wrapHeight = option.wrapHeight ? option.wrapHeight : 200;

        listener = option.listener;

        box = crEle(null, "sc-element-view");

        tab = new navTab(option);
        box.appendChild(tab.getTabNode());

        body = tab.getTabBodyNode();

        return box;
    }

    /**
     * 选项卡
     */
    function navTab(option){
        var tab = crEle(null, "sc-nav-tab");
        var tabHeadRow = crEle(null, "sc-nav-row");
        var tabBodyRow = crEle(null, "sc-nav-row,sc-row-direction-column");

        var item = null;
        for(var i in list){
            item = list[i];
            item.init = false;

            let label = crEle("label", item.class);
            label.innerText = item.label;
            tabHeadRow.appendChild(label);

            let content = crEle(null, "sc-nav-content");
            item.source = label;
            item.target = content;
    
            tabBodyRow.appendChild(content);

            if(item.active){
                content.classList.add("active");
                lastTabItem = item;
            }
        }

        var active = crEle("div", "sc-nav-active," + lastTabItem.class);
        tabHeadRow.appendChild(active);

        tabHeadRow.addEventListener("click",(e)=>{
            if(e.target.tagName.toLowerCase() == "label"){
                this.selectTab(e.target, option);
            }
        });

        tab.appendChild(tabHeadRow);
        tab.appendChild(tabBodyRow);

        this.getTabNode = function(){
            return tab;
        }

        this.getTabBodyNode = function(){
            return tabBodyRow;
        }

        this.selectTab = function(node, opt){
            let clazz = node.getAttribute("class");
            active.classList.remove(lastTabItem.class);
            active.classList.add(clazz);

            list.forEach(item=>{
                if(item.source == node){
                    item.target.classList.add("active");
                    lastTabItem = item;
                }else{
                    item.target.classList.remove("active");
                }
            });

            tabBodyRow.style.height = wrapHeight + "px";

            afterSwitchTab(lastTabItem, option.listener, opt);
        }

        afterSwitchTab(lastTabItem, option.listener, null);
    }

    /**
     * 切换tab后
     * @param {*} item 
     * @param {*} listener
     * @param {*} option 
     */
    var afterSwitchTab = function(item, listener, option){
        option = option ? option : {};
        
        if(item.label == "文档结构"){
            searchCondition = searchConditionForDoc;
            searchCondition.container = item.target;

            lazyLoadElements = lazyLoadElementsForDoc;

            if(item.init){
                return;
            }

            lazyLoadElementsForDoc = {type: "document"};
            lazyLoadElements = lazyLoadElementsForDoc;

            item.init = true;
            item.target.innerHTML = "";

            createSearchCondition(item.target, ()=>{
                let pageList = listener(item.command);

                lazyLoadElementsForDoc = {type: "document"};
                lazyLoadElements = lazyLoadElementsForDoc;
                
                let tree = item.target.querySelector(".sc-json-tree");
                if(tree){
                    tree.parentNode.removeChild(tree);
                }
                createDocumentStruct(item.target, pageList);
            });

            // let pageList = listener(item.command);
            // createDocumentStruct(item.target, pageList);
        }else if(item.label == "元素结构"){   
            searchCondition = {
                container: item.target,
                //显示样式
                showStyle: true,
                //显示包围盒
                showRect: true,
                //显示归属行
                showRow: true,
                //显示行文本
                showText: true,
            };

            lazyLoadElements = lazyLoadElementsForElement;
        }else if(item.label == "元素属性"){
        }
    }

    /**
     * 获取组件标题
     * @returns 
     */
    this.getTitle = function(){
        return "结构属性";
    }

    /**
     * 查询条件
     */
    var searchCondition = null;

    /**
     * 文档查询条件
     */
    var searchConditionForDoc = {
        //元素类型
        type: "",
        //属性名称
        name: "",
        //节点树容器
        container: null,
        //节点树收起标志
        collapsed: false,
        //起始页码
        beginPageNum: 1,
        //结束页码
        endPageNum: 1,
        //显示页眉
        showHead: false,
        //显示页体
        showBody: true,
        //显示页脚
        showFoot: false,
        //显示函数
        showFunction: false,
        //显示样式
        showStyle: true,
        //显示包围盒
        showRect: true,
        //显示归属行
        showRow: true,
        //显示行文本
        showText: true,
    };

    /**
     * 懒加载元素
     */
    var lazyLoadElements = null;
    var lazyLoadElementsForDoc = null;
    var lazyLoadElementsForElement = null;
    
    const FONT_SIZE = "14px";
    const FONT_FAMILY = "Arial";

    /**
     * 创建搜索条件视图
     * @param {*} container 
     */
    var createSearchCondition = function(container, callback){
        var condition = crEle("div");

        var row = crEle("div", "sc-flex-row");
        var input = crEle("input");

        input.type = "text";
        input.style.margin = "5px";
        input.placeholder = "输入属性过滤条件";
        input.addEventListener("input",(e)=>{
            searchConditionForDoc.name = e.currentTarget.value;
        });
        input.addEventListener("keydown",(e)=>{
            if(e.key.toLowerCase() != "enter") return;
            searchConditionForDoc.name = e.currentTarget.value;
            callback();
        });

        var typeList = [
            {title: "全部", name: "", selected: true},
            {title: "文本", name: "sText"},
            {title: "段落", name: "sParagraph"},
            {title: "表格", name: "sTable"},
            {title: "图片", name: "sLayer"},
            {title: "输入域", name: "sInput"},
            {title: "单选框", name: "sRadio"},
            {title: "复选框", name: "sCheckBox"},
            {title: "线条", name: "sLayer"},
            {title: "分页符", name: "sBreakline"},
            {title: "医学表达式", name: "sLayer"},
            {title: "条码", name: "sLayer"},
            {title: "二维码", name: "sLayer"},
        ];

        var select = crEle("select");
        select.style.height = "23px";

        for(let i in typeList){
            let option = crEle("option");
            option.value = typeList[i].name;
            option.innerText = typeList[i].title;
            select.append(option);
        }

        select.addEventListener("change", (e)=>{
            let val = e.currentTarget.value;
            searchConditionForDoc.type = val;
        });

        var filterBtn = crEle("button");
        filterBtn.style.padding = "4px 3px";
        filterBtn.style.marginRight = "5px";
        filterBtn.addEventListener("click", (e)=>{
            let pNode = e.currentTarget.parentNode;
            let dialog = pNode.querySelector(".sc-element-dialog");
            if(!dialog){
                dialog = createDialog(pNode, callback);
            }
            dialog.open();
        });

        var filterImage = crEle("img");
        filterImage.style.width = "10px";
        filterImage.style.height = "10px";
        filterImage.src = scToolbarResource.filter;

        filterBtn.append(filterImage);

        var btn = crEle("button");
        btn.style.padding = "4px 3px";
        btn.addEventListener("click", ()=>{
            callback();
        });

        var image = crEle("img");
        image.style.width = "10px";
        image.style.height = "10px";
        image.src = scToolbarResource.refresh;

        btn.append(image);
        
        row.append(select);
        row.append(input);
        row.append(filterBtn);
        row.append(btn);
        condition.append(row);

        var rowPage = crEle("div", "sc-flex-row"); 
        rowPage.style.display = "flex";

        let inputPageBegin = crEle("input");
        inputPageBegin.type = "text";
        inputPageBegin.value = 1;
        inputPageBegin.style.margin = "0px 5px 5px 0px";
        inputPageBegin.placeholder = "起始页";
        inputPageBegin.addEventListener("input", (e)=>{
            searchConditionForDoc.beginPageNum = parseInt(e.currentTarget.value);
        });

        let inputPageEnd = crEle("input");
        inputPageEnd.type = "text";
        inputPageEnd.value = 1;
        inputPageEnd.style.margin = "0px 0px 5px 5px";
        inputPageEnd.placeholder = "结束页";
        inputPageEnd.addEventListener("input", (e)=>{
            searchConditionForDoc.endPageNum = parseInt(e.currentTarget.value);
        });

        let text = crEle("span");
        text.innerText = "-";
        text.style.height = "28px";

        rowPage.append(inputPageBegin);
        rowPage.append(text);
        rowPage.append(inputPageEnd);

        condition.append(rowPage);

        var list = [
            {title: "显示页眉", name:"showHead", checked: searchConditionForDoc.showHead},
            {title: "显示页脚", name:"showFoot", checked: searchConditionForDoc.showFoot},
            {title: "显示页体", name:"showBody", checked: searchConditionForDoc.showBody},
            {title: "显示函数", name:"showFunction", checked: searchConditionForDoc.showFunction},
        ]

        var group = crEle("div", "sc-element-group");

        for(let i in list){
            let item = list[i];
            let row = crEle("div");
            let label = crEle("label", "sc-element-label");
            let checkbox = crEle("input");
            checkbox.setAttribute("type", "checkbox");
            checkbox.checked = item.checked;
            checkbox.addEventListener("change", (e)=>{
                searchConditionForDoc[item.name] = e.currentTarget.checked;
                callback();
            });
    
            label.innerText = item.title;
            label.prepend(checkbox);
    
            row.append(label);
            group.append(row);
        }
        
        condition.append(group);
        container.append(condition);

        searchConditionForDoc.height = 145;
    }

    /**
     * 创建对话框
     * @param {*} node 
     */
    var createDialog = function(node, callback){
        let dialog = crEle("div", "sc-element-dialog");
        node.append(dialog);

        dialog.open = function(){
            this.style.display = "block";
            this.style.right = "0px";
            this.style.top = "0px";
        }
        dialog.close = function(){
            this.style.display = "none";
        }
        
        var list = [
            {title: "显示样式", name:"showStyle", checked: searchConditionForDoc.showStyle},
            {title: "显示包围盒", name:"showRect", checked: searchConditionForDoc.showRect},
            {title: "显示归属行", name:"showRow", checked: searchConditionForDoc.showRow},
            {title: "显示行文本", name:"showText", checked: searchConditionForDoc.showText},
        ]

        var group = crEle("div", "sc-element-group");

        for(let i in list){
            let item = list[i];
            let row = crEle("div");
            let label = crEle("label", "sc-element-label");
            let checkbox = crEle("input");
            checkbox.setAttribute("type", "checkbox");
            checkbox.setAttribute("name", item.name);
            checkbox.checked = item.checked;
    
            label.innerText = item.title;
            label.prepend(checkbox);
    
            row.append(label);
            group.append(row);
        }

        dialog.append(group);

        var div = crEle("div");
        div.style.textAlign = "center";

        var okBtn = crEle("button", "sc-dialog-button");
        okBtn.innerText = "确定";
        okBtn.style.marginRight = "5px";
        okBtn.addEventListener("click", (e)=>{
            let boxes = dialog.querySelectorAll("input[type='checkbox']");
            for(let i = 0; i < boxes.length; i++){
                let box = boxes[i];
                searchConditionForDoc[box.getAttribute("name")] = box.checked;
            }
            dialog.close();
            callback();
        });

        var cancelBtn = crEle("button", "sc-dialog-button");
        cancelBtn.innerText = "取消";
        cancelBtn.addEventListener("click", ()=>{
            dialog.close();
        });

        div.append(okBtn);
        div.append(cancelBtn);

        dialog.append(div);

        return dialog;
    }

    /**
     * 创建文档结构视图
     * @param {*} container 
     * @param {*} pageList 
     * @param {*} opt 
     */
    var createDocumentStruct = function(container, pageList, opt){
        let jsonTree = createJsonTree({
            height: wrapHeight - searchCondition.height + "px",
            overflow: "auto"
        });
        container.append(jsonTree);

        jsonTree.loading = true;

        setTimeout(()=>{
            loadData(jsonTree, pageList, opt);
        }, 50);
    }

    /**
     * 加载数据
     * @param {*} jsonTree 
     * @param {*} pageList 
     * @param {*} opt 
     */
    var loadData = function(jsonTree, pageList, opt){
        let marginLeft = opt && opt.marginLeft ? parseFloat(opt.marginLeft) : 0;
        let areaStyle = {
            "marginLeft": marginLeft + 10 + "px"
        };
        let rowStyle = {
            "marginLeft": marginLeft + 10 + "px"
        };
        let elementStyle = {
            "font-weight": "bold",
            "marginLeft": marginLeft + 10 + "px"
        };
        let propStyle = {
            "font-size": FONT_SIZE,
            "font-family": FONT_FAMILY,
            "font-weight": "normal",
            "marginLeft": marginLeft + 28 + "px"
        };

        let wrap = crEle("div");

        pageList.forEach((page, pageIndex)=>{
            if(searchCondition.beginPageNum > pageIndex || searchCondition.endPageNum < pageIndex){
                return;
            }

            let pageView = createRowView("page (" + pageIndex + ")", true);
            wrap.append(pageView);

            let areas = {};
            
            if(searchCondition.showHead){
                areas.head = createRowView("head", true, {style: areaStyle});
                pageView.append(areas.head);
            }

            if(searchCondition.showBody){
                areas.body = createRowView("body", true, {style: areaStyle});
                pageView.append(areas.body);
            }

            if(searchCondition.showFoot){
                areas.foot = createRowView("foot", true, {style: areaStyle});
                pageView.append(areas.foot);
            }

            page.forEach((row, index, type)=>{
                if(!areas[type]) return;
                let rowView = createRowView("row-" + index, true, {style: rowStyle});
                areas[type].append(rowView);

                row.forEach((element)=>{
                    if(searchCondition.type && searchCondition.type != element._sType){
                        return;
                    }

                    createElementView(element, rowView, {
                        elementStyle: elementStyle,
                        propStyle: propStyle
                    });
                });
            });
        });

        jsonTree.loading = false;
        jsonTree.append(wrap);
    }

    /**
     * 根据属性名称过滤
     * @param {*} key 
     * @param {*} obj
     */
    var filterByName = function(key, obj){
        let flg = true;

        if(searchCondition.name) {
            if(Array.isArray(obj) || isObject(obj[key])) {
                flg = false;
            }else if(typeof(key) == "string" && key.indexOf(searchCondition.name) > -1){
                flg = false;
            }
        }else{
            flg = false;
        }

        if(!searchCondition.showRect){
            if(key == "__boundRect"){
                flg = true;
            }
        }

        if(!searchCondition.showRow){
            if(key == "__rows"){
                flg = true;
            }
        }

        if(!searchCondition.showStyle){
            if(key == "style"){
                flg = true;
            }
        }

        if(!searchCondition.showText){
            if(key == "__texts"){
                flg = true;
            }
        }
        
        return flg;
    }

    /**
     * 创建json树节点
     * @returns 
     */
    var createJsonTree = function(style){
        let row = crEle("div", "sc-json-row,sc-row-control");
        row.style.background = "#f1f1f1";
        row.style.marginBottom = "5px";
        row.style.padding = "2px";

        let image = crEle("img", "sc-json-arrow2");

        image.style.verticalAlign = "-2px";
        image.src = searchCondition.collapsed 
            ? scToolbarResource.arrowAllCollapsed
            : scToolbarResource.arrowAllExpand;

        let text = crEle("span");
        text.innerText = searchCondition.collapsed ? "全部展开" : "全部收起";
        text.style.fontSize = "12px";

        row.append(image);
        row.append(text);

        row.addEventListener("click", (e)=>{
            let display = searchCondition.collapsed ? "" : "none";
            let collapsed = searchCondition.collapsed ? "false" : "true";
            let rowRootList = searchCondition.container.querySelectorAll(".sc-row-root");

            for(let i = 0; i < rowRootList.length; i++){
                let rowRoot = rowRootList[i];

                let arrow = rowRoot.querySelector(".sc-json-arrow");
                arrow.setAttribute("data-collapsed", collapsed);

                if(collapsed){
                    arrow.classList.remove("sc-arrow-expand");
                }else{
                    arrow.classList.add("sc-arrow-expand");
                }

                let child = null;
                for(let j = 0; j < rowRoot.parentNode.children.length; j++){
                    child = rowRoot.parentNode.children[j];
                    if(child === rowRoot) continue;
                    child.style.display = display;
                }
            }

            searchCondition.collapsed = !searchCondition.collapsed;
            image.src = searchCondition.collapsed 
                ? scToolbarResource.arrowAllCollapsed 
                : scToolbarResource.arrowAllExpand;
            text.innerText = searchCondition.collapsed ? "全部展开" : "全部收起";
        });

        let treeNode = crEle("div", "sc-json-tree");
        for(let i in style){
            treeNode.style[i] = style[i];
        }

        treeNode.append(row);

        let emptyNode = crEle("div", "sc-loading");
        emptyNode.innerText = "加载中..."

        treeNode.append(emptyNode);
        
        Object.defineProperty(treeNode, "loading", {
            set: function(val){
                let loading = this.querySelector(".sc-loading");
                if(!loading) return;

                loading.style.display = val ? "" : "none";

                let control = this.querySelector(".sc-row-control");
                control.style.display == val ? "none" : "";
            }
        });

        return treeNode;
    }

    /**
     * 根据json对象创建视图
     * @param {*} json 
     * @param {*} parentNode
     * @param {*} opt 
     */
    var createJsonView = function(json, parentNode, opt){
        let propStyle1 = {
            "font-size": FONT_SIZE,
            "font-family": FONT_FAMILY,
            "font-weight": "normal",
            "marginLeft": 28 + "px"
        };

        let propStyle2 = {
            "font-size": FONT_SIZE,
            "font-family": FONT_FAMILY,
            "font-weight": "normal",
            "marginLeft": 28 + "px"
        };

        let propStyle3 = {
            "font-size": FONT_SIZE,
            "font-family": FONT_FAMILY,
            "font-weight": "normal",
            "marginLeft": 10 + "px"
        };

        let value = null;
        let isEmpty = false;

        for(let i in json){
            if(filterByName(i, json)) continue;

            let jsonObj = json[i];

            value = null;
            isEmpty = false;

            if(jsonObj instanceof Function){
                if(!searchCondition.showFunction) continue;
                value = "function";
                isEmpty = true;
            }else if(Array.isArray(jsonObj) && jsonObj.length == 0){
                if(jsonObj.length == 0){
                    value = "[]";
                    isEmpty = true;
                }
            }else if(isObject(jsonObj)){
                if(isObjectEmpty(jsonObj)){
                    value = "{}";
                    isEmpty = true;
                }else if(jsonObj._sType){
                    createLoadLink(i, jsonObj, parentNode, {});
                    continue;
                }else if(jsonObj instanceof Image){
                    value = "img";
                    isEmpty = true;
                }
            }else if(typeof(jsonObj) == "string"){
                value = jsonObj === null ? null : jsonObj === "" ? "" : ("\"" + jsonObj + "\"");
                isEmpty = true;
            }else if(typeof(jsonObj) == "number"){
                value = jsonObj;
                isEmpty = true;
            }else if(typeof(jsonObj) == "boolean"){
                value = jsonObj;
                isEmpty = true;
            }

            let kvNode = createKeyValueView(
                i, 
                value, 
                !isEmpty,
                {style: isEmpty ? propStyle1 : propStyle3}
            );
            parentNode.append(kvNode);

            if(isEmpty) continue;

            for(let j in jsonObj){
                if(filterByName(j, jsonObj)) continue;

                if(jsonObj[j] instanceof Function){
                    if(!searchCondition.showFunction) continue;
                    let propView = createKeyValueView(
                        j, 
                        `function(${getParamNames(jsonObj[j])})`, 
                        false,
                        {style: propStyle2}
                    );
                    kvNode.append(propView);
                }else if(isObject(jsonObj[j])){
                    if(jsonObj[j]._sType){
                        createElementView(jsonObj[j], kvNode, {
                            elementStyle: propStyle3,
                            propStyle: propStyle2
                        });
                    }else{
                        let propView = createKeyValueView(j, "", true, {style: propStyle3});
                        createJsonView(jsonObj[j], propView);
                        kvNode.append(propView);
                    }
                }else{
                    let propView = createKeyValueView(
                        j, 
                        jsonObj[j], 
                        isObject(jsonObj[j]), 
                        {style: propStyle2}
                    );
                    kvNode.append(propView);
                }
            }
        }
    }

    /**
     * 创建加载链接
     * @param {*} key
     * @param {*} element 
     * @param {*} parentNode
     * @param {*} opt
     */
    var createLoadLink = function(key, element, parentNode, opt){
        let uuid = createUuid();

        let elementStyle = {
            "font-size": FONT_SIZE,
            "font-family": FONT_FAMILY,
            "font-weight": "normal",
            "marginLeft": 10 + "px"
        };

        let propStyle = {
            "font-size": FONT_SIZE,
            "font-family": FONT_FAMILY,
            "font-weight": "normal",
            "marginLeft": 28 + "px"
        };

        lazyLoadElements[uuid] = element;
        
        let link = crEle("span","sc-element-load");
        link.innerHTML = "<span class='sc-element-description'>" + element._sType + " (...)</span>";
        
        let callback = (e)=>{
            let parentNode = e.currentTarget.parentNode.parentNode;
            createElementView(lazyLoadElements[uuid], parentNode, {
                elementStyle: elementStyle,
                propStyle: propStyle
            });
            
            let desc = link.querySelector(".sc-element-description");
            desc.parentNode.removeChild(desc);
            link.removeEventListener("click", callback);
        };

        let kvNode = createKeyValueView(
            key, 
            link, 
            true,
            { 
              style: elementStyle, 
              collapsed: true, 
              lazyLoad: callback 
            }
        );

        parentNode.append(kvNode);
    }

    /**
     * 获取对象不可遍历属性
     */
    var getNonEnumerableProps = function(obj){
        const props = Object.getOwnPropertyNames(obj)
          .filter(prop => {
            const desc = Object.getOwnPropertyDescriptor(obj, prop);
            return desc.enumerable === false;
          });
        let json = {};
        for(let i in props){
            json[props[i]] = obj[props[i]];
        }
        return json;
    }

    /**
     * 获取函数参数名
     * @param {*} func 
     * @returns 
     */
    var getParamNames = function(func){
        const funcString = func.toString();
        const matches = funcString.match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m);
        const paramNames = matches && matches[1].split(',').map(function(param) {
          return param.trim();
        });
        return paramNames;
    }

    /**
     * 是否是对象
     * @param {*} value 
     * @returns 
     */
    var isObject = function(value){
        return value instanceof Array || value instanceof Object;
    }

    /**
     * 判断是否是空对象
     * @param {*} value 
     * @returns 
     */
    var isObjectEmpty = function(value){
        let isEmpty = true;

        if(value instanceof Object){
            for(let i in value){
                isEmpty = false;
                break;
            }
        }

        return isEmpty;
    }

    /**
     * 创建行视图
     * @param {*} title 
     * @param {*} opt 
     */
    var createRowView = function(title, hasChildren, opt){
        let viewNode = crEle("div", "sc-json-row");
        let rowNode = viewNode;

        if(opt && opt.style){
            for(let i in opt.style){
                rowNode.style[i] = opt.style[i];
            }
        }

        if(hasChildren){
            rowNode = crEle("div", "sc-json-row,sc-row-root");
            let arrowNode = createArrowView(rowNode, opt);
            rowNode.append(arrowNode);
            viewNode.append(rowNode);
        }

        let titleNode = crEle("span", "sc-json-title");
        titleNode.innerHTML = title;

        if(opt && opt.bindEvent){
            titleNode.classList.add("sc-element-hover");
        }

        rowNode.append(titleNode);

        return viewNode;
    }
    
    /**
     * 创建键值对视图
     * @param {*} key 
     * @param {*} value 
     * @param {*} hasChildren
     * @param {*} opt 
     */
    var createKeyValueView = function(key, value, hasChildren, opt){
        let viewNode = crEle("div", "sc-json-row-block");
        let rowNode = viewNode;

        if(opt && opt.style){
            for(let i in opt.style){
                rowNode.style[i] = opt.style[i];
            }
        }

        if(hasChildren){
            rowNode = crEle("div", "sc-json-row,sc-row-root");
            let arrowNode = createArrowView(rowNode, opt);
            rowNode.append(arrowNode);
            viewNode.append(rowNode);
        }

        let keyNode = crEle("span", "sc-json-key");
        keyNode.innerText = key + ":";
        let valueNode = crEle("span", "sc-json-value");
        if(value && typeof(value) == "object" && value.tagName){
            valueNode.append(value);
        }else{
            valueNode.innerHTML = value;
        }

        rowNode.append(keyNode);
        rowNode.append(valueNode);

        return viewNode;
    }

    /**
     * 创建箭头节点视图
     * @param {*} opt 
     */
    var createArrowView = function(parentNode, opt){
        let collapsed = opt && opt.collapsed != null 
            ? opt.collapsed 
            : searchCondition.collapsed;
        let arrowNode = crEle("div","sc-json-arrow");

        if(collapsed){
            arrowNode.classList.remove("sc-arrow-expand");
        }else{
            arrowNode.classList.add("sc-arrow-expand");
        }

        arrowNode.setAttribute("data-collapsed", collapsed ? "true" : "false");
        arrowNode.addEventListener("click", (e)=>{
            if(opt && opt.lazyLoad){
                opt.lazyLoad(e);
                opt.lazyLoad = null;
            };

            let pNode = e.currentTarget.parentNode.parentNode;
            let collapsed = arrowNode.getAttribute("data-collapsed") == "true";
            for(let i = 0; i < pNode.children.length; i++){
                if(pNode.children[i] === parentNode) continue;
                pNode.children[i].style.display = collapsed ? "" : "none";
            }

            e.currentTarget.setAttribute("data-collapsed", collapsed ? "false" : "true");
            
            if(collapsed){
                e.currentTarget.classList.add("sc-arrow-expand");
            }else{
                e.currentTarget.classList.remove("sc-arrow-expand");
            }
        });

        return arrowNode;
    }

    /**
     * 创建元素视图
     * @param {*} element 
     * @param {*} parentNode 
     * @param {*} opt 
     */
    var createElementView = function(element, parentNode, opt){
        let elementStyle = opt && opt.elementStyle;
        let propStyle = opt && opt.propStyle;

        let eleView = createRowView(
            "<span class='sc-json-type'>" + element._sType + "</span>", 
            true, {style: elementStyle, bindEvent: true});
        parentNode.append(eleView);
        
        let prop = null;
        for(let i in element){
            if(filterByName(i, element)) continue;

            prop = element[i];
            if(prop instanceof Function){
                if(!searchCondition.showFunction) continue;
                let propView = createKeyValueView(i, 
                    `function(${getParamNames(prop)})`, 
                    false, 
                    {style: propStyle}
                );
                eleView.append(propView);
            }else if(isObject(prop)){
                let jo = {};
                jo[i] = prop;
                createJsonView(
                    jo, 
                    eleView
                );
            }else{
                let propView = createKeyValueView(
                    i, 
                    prop ? prop : prop === "" ? "\"\"" : prop === null ? "null" : prop, 
                    false, 
                    {style: propStyle}
                );
                eleView.append(propView);
            }
        }

        //获取不可遍历属性
        let props = getNonEnumerableProps(element);
        createJsonView(
            props, 
            eleView
        );

        //创建table元素视图
        createTableView(element, eleView, {
            style: {
                marginLeft: parseFloat(elementStyle.marginLeft)
            }
        });
    }

    /**
     * 创建表格视图
     * @param {*} element 
     * @param {*} parentNode 
     * @param {*} opt 
     */
    var createTableView = function(element, parentNode, opt){
        if(element._sType != "sTable") return;
        
        let marginLeft = opt && opt.style ? opt.style.marginLeft : 0;
        let style1 = {
            marginLeft: marginLeft + "px"
        };
        let style2 = {
            marginLeft: marginLeft + 10 + "px"
        };

        let colsView = createRowView("columns", true, {style: style1});
        parentNode.append(colsView);

        let cols = element.getColumns();
        for(let i = 0; i < cols.length; i++){
            let colView = createRowView("column (" + i + ")", true, {style: style2});
            createJsonView(cols[i], colView);
            colsView.append(colView);
        }

        let rowsView = createRowView("rows", true, {style: style1});
        parentNode.append(rowsView);

        let rows = element.getRows();
        for(let i = 0; i < rows.length; i++){
            let rowView = createRowView("row (" + i + ")", true, {style: style2});
            let cellsView = createRowView("cells", true, {style: style2});
            
            let cells = rows[i].getCells();
            for(let j = 0; j < cells.length; j++){
                let cellView = createRowView("cell (" + j + ")", true, {style: style2});
                createJsonView(cells[j], cellView);
                cellsView.append(cellView);
            }

            rowView.append(cellsView);
            rowsView.append(rowView);
        }
    }

    var locked = null;

    /**
     * 通知
     * @param {*} eventType 
     * @param {*} opt 
     */
    this.notify = function(eventType, opt){
        if(eventType == "mousedown"){
            if(tab){
                if(locked) {
                    clearTimeout(locked);
                    locked = null;
                }

                if(lastTabItem.name == "elementStruct"){
                    lazyLoadElementsForElement = {type: "element"};
                    lazyLoadElements = lazyLoadElementsForElement;

                    let item = list.find(it=>it.name == "elementStruct");
                    tab.selectTab(item.source);
    
                    item.target.innerHTML = "";
    
                    let jsonTree = item.target.querySelector(".sc-json-tree");
                    if(!jsonTree){
                        jsonTree = createJsonTree({
                            height: wrapHeight - 60,
                            overflow: "auto"
                        });
                    }
    
                    item.target.append(jsonTree);
    
                    let dataWrap = jsonTree.querySelector(".sc-data-wrap");
                    if(!dataWrap){
                        dataWrap = crEle("div", "sc-data-wrap");
                        jsonTree.append(dataWrap);
                    }
                    
                    dataWrap.innerHTML = "";
                    jsonTree.loading = true;
    
                    locked = setTimeout(()=>{
                        createElementView(opt.element, dataWrap, {
                            elementStyle: {
                                "font-size": FONT_SIZE,
                                "font-family": FONT_FAMILY,
                                "font-weight": "normal",
                                "marginLeft": 10 + "px"
                            },
                            propStyle: {
                                "font-size": FONT_SIZE,
                                "font-family": FONT_FAMILY,
                                "font-weight": "normal",
                                "marginLeft": 28 + "px"
                            }
                        });
    
                        jsonTree.loading = false;
                        locked = null;
                    }, 50);
                }else if(lastTabItem.name = "elementProperties"){
                }
            }
        }else if(eventType == "toolbarStatusChange"){
            if(opt.value == false){
                lazyLoadElements = null;
                lazyLoadElementsForDoc = null;
                lazyLoadElementsForElement = null;
                
                for(let i in list){
                    list[i].target.innerHTML = "";
                }
            }
        }
    }

    /**
     * 创建UUID
     * @returns 
     */
    var createUuid = function(){
        return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0,
            v = c == "x" ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

}